package alex.cicy.storage.redis;

import alex.cicy.AppContext;
import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;

import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.List;

public class RedisFactory {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private JedisPool jedisPool;
    private String lockSha;
    private String unlockSha;
    private String redisHost;
    private int    port;

    public void setRedisHost(String redisHost) {
        this.redisHost = redisHost;
    }


    public static RedisFactory get(String beanId) {
        return AppContext.getAppContext().getBean(beanId, RedisFactory.class);
    }

    public static RedisFactory get() {
        return AppContext.getAppContext().getBean(RedisNames.CACHE, RedisFactory.class);
    }
    @PostConstruct
    public void init() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(100);
        config.setMaxIdle(100);
        //config.setTestOnBorrow(true); 应该设置redis server timeout为0
        config.setMinEvictableIdleTimeMillis(-1);
        jedisPool = new JedisPool(config, redisHost, port, 30000);
    }

    private String getScript(String name) {
        try {
            InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("redis/"+name);
            byte[] bytes = new byte[input.available()];
            input.read(bytes);
            return new String(bytes);
        } catch (Exception e) {
            logger.error("", e);
            return null;
        }
    }

    public <T> T runWithJedis(JedisRunnable runnable) {
        Jedis jedis = jedisPool.getResource();
        try {
            T ret = (T) runnable.run(jedis);
            jedisPool.returnResource(jedis);
            return ret;
        } catch (Exception e) {
            getJedisPool().returnBrokenResource(jedis);
            throw Throwables.propagate(e);
        }
    }

    public List<Response<?>> runWithTx(TxRunnable runnable) {
        Jedis jedis = jedisPool.getResource();
        try {
            Transaction tx = jedis.multi();
            List<Response<?>> ret = runnable.run(tx);
            jedisPool.returnResource(jedis);
            return ret;
        } catch (Exception e) {
            getJedisPool().returnBrokenResource(jedis);
            throw Throwables.propagate(e);
        }
    }
    public void setPort(int port) {
        this.port = port;
    }

    public JedisPool getJedisPool() {
        return jedisPool;
    }

    public String getLockSha() {
        return lockSha;
    }

    public String getUnlockSha() {
        return unlockSha;
    }
}
